import type { AppointmentManagement } from '@shared/types/'
import type { BookingOptions, BookingOutcome } from '../strategy'
import { EventEmitter } from 'node:events'
import { v4 as uuidv4 } from 'uuid'
import { getLogger } from '../../logger/index'
import { TaskQueueManager } from './task-queue-manager'
import { WorkerPoolManager } from './worker-pool-manager'

// 惰性获取 logger，避免在模块加载时初始化
function getLoggerSafe() {
  try {
    return getLogger()
  }
  catch {
    // 如果 logger 未初始化，返回一个简单的 console logger
    return {
      debug: console.log.bind(console),
      info: console.log.bind(console),
      warn: console.warn.bind(console),
      error: console.error.bind(console),
    }
  }
}

/**
 * 多进程预约服务
 *
 * 统一管理任务队列和 Worker 进程池，提供多进程预约能力
 */
export class MultiprocessBookingService extends EventEmitter {
  private workerPool: WorkerPoolManager
  private taskQueue: TaskQueueManager
  private results: Map<string, BookingOutcome> = new Map()
  private isProcessing: boolean = false
  private initialized: boolean = false

  constructor(maxWorkers: number = 50) {
    super()
    this.workerPool = new WorkerPoolManager(maxWorkers)
    this.taskQueue = new TaskQueueManager()

    // 监听 Worker 事件
    this.workerPool.on('task:result', (taskId, result) => {
      this.results.set(taskId, result.data)
      this.taskQueue.complete(taskId)
      this.emit('task:completed', taskId, result)
    })

    this.workerPool.on('task:error', (taskId, error) => {
      this.results.set(taskId, { success: false, error: error.error })
      this.taskQueue.fail(taskId)
      this.emit('task:failed', taskId, error)
    })

    this.workerPool.on('task:lost', (taskId) => {
      getLoggerSafe().warn('任务丢失，需要重新分配', { taskId })
      // 可以在这里实现任务重试逻辑
      this.emit('task:lost', taskId)
    })

    // 启动任务处理循环
    this.startProcessing()
  }

  /**
   * 初始化进程池（预热 Worker 进程）
   */
  async initialize(): Promise<void> {
    if (this.initialized) {
      getLoggerSafe().warn('多进程服务已初始化，跳过重复初始化')
      return
    }

    getLoggerSafe().info('开始初始化多进程预约服务')

    // 预热进程池：启动所有Worker进程
    // 50个Worker的总内存约780MB，启动时间约2-3秒
    await this.workerPool.initialize()

    this.initialized = true

    getLoggerSafe().info('多进程预约服务初始化完成', {
      workerCount: this.workerPool.getStats().total,
      estimatedMemoryMB: this.workerPool.getStats().total * 15 + 30,
    })
  }

  /**
   * 启动任务处理循环
   */
  private startProcessing(): void {
    if (this.isProcessing) {
      return
    }

    this.isProcessing = true

    const processLoop = async () => {
      while (this.isProcessing) {
        const task = this.taskQueue.dequeue()
        if (task) {
          try {
            await this.workerPool.assignTask(task.id, task.payload)
          }
          catch (error) {
            // Worker 不可用，重新入队
            getLoggerSafe().warn('Worker 不可用，任务重新入队', {
              taskId: task.id,
              error: error instanceof Error ? error.message : String(error),
            })
            this.taskQueue.enqueue(task)
            await new Promise(resolve => setTimeout(resolve, 1000))
          }
        }
        else {
          // 队列为空，等待新任务
          await new Promise(resolve => setTimeout(resolve, 100))
        }
      }
    }

    processLoop().catch((err) => {
      getLoggerSafe().error('任务处理循环错误', { error: err })
      this.emit('error', err)
    })
  }

  /**
   * 执行预约任务
   */
  async bookWith(
    mode: 'playwright' | 'request',
    appointment: AppointmentManagement,
    options?: BookingOptions,
  ): Promise<BookingOutcome> {
    // 确保已初始化
    if (!this.initialized) {
      await this.initialize()
    }

    const taskId = uuidv4()

    // 确定优先级（文档中定义：HIGH=1, NORMAL=2, LOW=3）
    // 这里简化为：监控触发的为HIGH，其他为NORMAL
    const priority = options?.priority || 2 // 默认 NORMAL

    const task = {
      id: taskId,
      priority,
      payload: {
        mode,
        appointment,
        options,
      },
      createdAt: Date.now(),
      timeout: (options?.timeoutMs || 30000) * 2, // 任务超时 = 执行超时 * 2
    }

    // 入队
    this.taskQueue.enqueue(task)

    getLoggerSafe().debug('预约任务已入队', {
      taskId,
      mode,
      priority,
      queueLength: this.taskQueue.getQueueLength(),
    })

    // 等待结果
    return new Promise<BookingOutcome>((resolve, reject) => {
      // 使用对象存储处理函数引用，避免循环引用问题
      const handlers: {
        onCompleted?: (completedTaskId: string) => void
        onFailed?: (failedTaskId: string, error: any) => void
      } = {}

      // 定义清理函数
      const cleanup = () => {
        if (handlers.onCompleted)
          this.removeListener('task:completed', handlers.onCompleted)
        if (handlers.onFailed)
          this.removeListener('task:failed', handlers.onFailed)
      }

      // 先定义 onFailed
      handlers.onFailed = (failedTaskId: string, error: any) => {
        if (failedTaskId === taskId) {
          cleanup()
          const outcome = this.results.get(taskId)
          this.results.delete(taskId) // 清理结果缓存
          if (outcome) {
            resolve(outcome)
          }
          else {
            reject(new Error(error.error || '任务执行失败'))
          }
        }
      }

      // 然后定义 onCompleted（可以引用已定义的 onFailed）
      handlers.onCompleted = (completedTaskId: string) => {
        if (completedTaskId === taskId) {
          cleanup()
          const outcome = this.results.get(taskId)
          if (outcome) {
            this.results.delete(taskId) // 清理结果缓存
            resolve(outcome)
          }
          else {
            reject(new Error('任务完成但未找到结果'))
          }
        }
      }

      this.on('task:completed', handlers.onCompleted)
      this.on('task:failed', handlers.onFailed)

      // 超时处理
      setTimeout(() => {
        cleanup()
        this.results.delete(taskId)
        reject(new Error('任务执行超时'))
      }, task.timeout)
    })
  }

  /**
   * 关闭服务
   */
  async shutdown(): Promise<void> {
    getLoggerSafe().info('开始关闭多进程预约服务')
    this.isProcessing = false
    await this.workerPool.shutdown()
    this.initialized = false
    getLoggerSafe().info('多进程预约服务已关闭')
  }

  /**
   * 获取统计信息
   */
  getStats(): {
    queueLength: number
    pendingCount: number
    workerStats: {
      total: number
      idle: number
      busy: number
      dead: number
    }
  } {
    return {
      queueLength: this.taskQueue.getQueueLength(),
      pendingCount: this.taskQueue.getPendingCount(),
      workerStats: this.workerPool.getStats(),
    }
  }

  /**
   * 检查是否已初始化
   */
  isInitialized(): boolean {
    return this.initialized
  }
}
